package com.gmscosmo.janus.netty;

import com.alibaba.fastjson.JSONObject;
import com.gmscosmo.common.APIPath;
import com.gmscosmo.common.JanusIMSignaling;
import com.gmscosmo.janus.engine.AVEngineKit;
import com.gmscosmo.request.ConfigureBody;
import com.gmscosmo.request.JoinBody;
import com.gmscosmo.request.Jsep;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * @author stephen.qiu
 */
@Component
@ChannelHandler.Sharable
public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    @Autowired
    AVEngineKit avEngineKit;
    @Autowired
    ConnectionManager connectionManager;

    /**
     * 接受客户端发送的消息，执行相关函数操作
     *
     * @param ctx 通道相关信息
     * @param msg 前端，也就是客户端发来的消息内容
     * @throws Exception 异常
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        JSONObject object = JSONObject.parseObject(msg.text());
        System.out.println(object);
        String action = object.getString("action");
        String response = null;
        String userId = object.getString("userId");
        String targetUserId = object.getString("targetUserId");
        try {
            switch (action) {
                case "connect":
                    connectionManager.put(userId, ctx.channel());
                    System.out.println(userId + "上线");
                    response = "Connected";
                    break;
                case "disConnect":
                    connectionManager.remove(userId);
                    System.out.println(userId + "下线");
                    response = "disConnected";
                    break;
                case APIPath.OFFER:
                    Jsep offer = object.getObject("jsep", Jsep.class);
                    ConfigureBody configureBody = new ConfigureBody();
                    configureBody.setAudio(true);
                    configureBody.setAudio(true);
                    response = avEngineKit.sendOffer(userId, offer, configureBody);
                    break;
                case APIPath.JOIN_PUB:
                    JoinBody joinBody = object.getObject("joinBody", JoinBody.class);
                    response = avEngineKit.handleJoinAndPub(userId, joinBody);
                    break;
                case APIPath.JOIN_SUB:
                    response = avEngineKit.handleJoinAndSub(userId, targetUserId, new JoinBody());
                    break;
                case APIPath.TRICKLE:
                    String candidate = object.getString("candidate");
                    response = avEngineKit.sendCandidate(userId, targetUserId, candidate);
                    break;
                case APIPath.KEEP_A_LIVE:
                    response = avEngineKit.keepalive(userId);
                    break;
                case APIPath.LEAVE:
                    response = avEngineKit.handleLeave(userId);
                    break;
                case APIPath.START:
                    Jsep answer = object.getObject("jsep", Jsep.class);
                    response = avEngineKit.start(userId, targetUserId, answer);
                    break;
                case APIPath.CONFIGURE:
                    response = avEngineKit.configure(userId, targetUserId, object.getObject("configureBody", ConfigureBody.class));
                    break;
                case APIPath.START_LIVE:
                    response = avEngineKit.startLive(userId);
                    break;
                case APIPath.STOP_LIVE:
                    response = avEngineKit.stopLive(userId);
                    break;
                case APIPath.WATCH_LIVE:
                    int roomId = object.getInteger("room");
                    response = avEngineKit.watchLive(userId, roomId);
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(response);
        TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(response);
        ctx.channel().writeAndFlush(textWebSocketFrame);
    }

    /**
     * 与客户端建立连接
     *
     * @param ctx -
     * @throws Exception 异常
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
    }

    /**
     * 处于运行状态
     *
     * @param ctx -
     * @throws Exception 异常
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().remoteAddress() + "连接");
    }

    /**
     * 关闭连接
     *
     * @param ctx -
     * @throws Exception 异常
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().remoteAddress() + "断开连接");
    }

    /**
     * 出现异常
     *
     * @param ctx   -
     * @param cause -
     * @throws Exception 异常
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        System.out.println("客户端网络断开，即将关闭异常客户端");
        //发生了异常后关闭连接，同时从channelGroup移除
        ctx.channel().close();
        System.out.println("成功关闭异常客户端");
    }
}